<template>
  <div class="myForm">
    <el-form
      :class="formClass"
      :model="form"
      :rules="rules"
      :show-message="showMessage"
      :size="size"
      @submit.native.prevent
      class="demo-form"
      label-position="right"
      ref="form"
    >
      <virtual-list
        :class="!isVirtaulList && 'non-virtual-list'"
        :remain="curVirtualListRemain"
        :size="virtualListSize"
        :start="virtualListStart"
        :variable="getVariableHeight"
      >
        <el-row :gutter="gutter" v-for="(curitem,index) in curData" :key="index" :ref="'row-' + index">
          <el-col
            :class="item.colClass"
            :key="item.model || index"
            :offset="item.offset || 0"
            :pull="item.pull || 0"
            :push="item.push || 0"
            :span="item.span || span"
            class="myForm-colClass virtual-list-item"
            v-for="(item,index) in curitem"
            :ref="'row-' + index + '-col-' + (item.model || index)"
          >
            <el-form-item
              :class="item.class"
              :label="item.label"
              :label-width="item.labelWidth || formLabelWidth"
              :prop="item.model"
              :rules="item.rules"
              v-if="!!(item.model || item.text)"
            >
              <!--text文本-->
              <my-text
                :content="form[item.model]"
                :disabled="item.disabled"
                v-if="item.type==='text'"
              ></my-text>
              <!--span文字-->
              <div v-else-if="item.type==='span'">
                <span v-html="item.text || form[item.model]"></span>
              </div>
              <!--icon图标-->
              <i :class="item.iconClass" @click="item.handleClick" v-else-if="item.type==='icon'"></i>
              <!--button按钮-->
              <my-button
                :disabled="item.disabled"
                :handleClick="item.handleClick"
                :icon="item.icon"
                :loading="item.loading"
                :options="item.options"
                :plain="item.plain"
                :round="item.round"
                :size="item.size"
                :text="item.text"
                :type="item.buttonType"
                v-else-if="item.type==='button'"
              ></my-button>
              <!--@update:model="val => form[item.model] = val"-->
              <!--input输入框-->
              <my-input
                :autosize="item.autosize"
                :blur="item.blur"
                :clearable="item.clearable"
                :disabled="item.disabled"
                :keydownEnter="item.keydownEnter"
                :limitMax="item.limitMax"
                :limitMin="item.limitMin"
                :model.sync="form[item.model]"
                :modelKey="item.model"
                :placeholder="item.placeholder"
                :readonly="item.readonly"
                :resize="item.resize"
                :rows="item.rows"
                :slotType="item.slotType"
                :tabindex="item.tabindex"
                :toFixed="item.toFixed"
                :type="item.inputType"
                v-else-if="item.type==='input'"
              >
                <!--有相关slot插槽-->
                <template slot="inputSlot" v-if="item.slotName">
                  <slot :name="item.slotName"></slot>
                </template>
              </my-input>
              <!--autocomplete输入补全建议框-->
              <my-autocomplete
                :disabled="item.disabled"
                :model.sync="form[item.model]"
                :options="item.options"
                :readonly="item.readonly"
                :slotType="item.slotType"
                v-else-if="item.type==='autocomplete'"
              >
                <template slot="autoCompleteSlot" v-if="item.slotName">
                  <slot :name="item.slotName"></slot>
                </template>
              </my-autocomplete>
              <!--inputNumber计数器-->
              <my-inputNumber
                :change="item.change"
                :controlsPosition="item.controlsPosition"
                :disabled="item.disabled"
                :max="item.max"
                :min="item.min"
                :model.sync="form[item.model]"
                v-else-if="item.type==='inputNumber'"
              ></my-inputNumber>
              <!--radio框-->
              <my-radio
                :change="item.change"
                :disabled="item.disabled"
                :model.sync="form[item.model]"
                :options="item.options"
                :props="item.props"
                v-else-if="item.type==='radio'"
              ></my-radio>
              <!--checkbox多选框-->
              <my-checkbox
                :change="item.change"
                :disabled="item.disabled"
                :falseLabel="item.falseLabel"
                :indeterminate="item.indeterminate"
                :model.sync="form[item.model]"
                :options="item.options"
                :props="item.props"
                :trueLabel="item.trueLabel"
                v-else-if="item.type==='checkbox'"
              ></my-checkbox>
              <!--select下拉框-->
              <my-select
                :change="item.change"
                :clearable="item.clearable"
                :collapseTags="item.collapseTags"
                :disabled="item.disabled"
                :filterable="item.filterable"
                :loading="item.loading"
                :model.sync="form[item.model]"
                :modelKey="item.model"
                :multiple="item.multiple"
                :options="item.options"
                :props="item.props"
                :valueKey="item.valueKey"
                :visibleChange="item.visibleChange"
                v-else-if="item.type==='select'"
              ></my-select>
              <!--datepicker日期选择框-->
              <my-datepicker
                :change="item.change"
                :clearable="item.clearable"
                :disabled="item.disabled"
                :editable="item.editable"
                :model.sync="form[item.model]"
                :pickerOptions="item.pickerOptions"
                :type="item.dateType"
                :valueFormat="item.valueFormat"
                v-else-if="item.type==='datePicker'"
              ></my-datepicker>
              <!--Switch 开关-->
              <my-switch
                :activeColor="item.activeColor"
                :activeIconClass="item.activeIconClass"
                :activeText="item.activeText"
                :activeValue="item.activeValue"
                :change="item.change"
                :disabled="item.disabled"
                :inactiveColor="item.inactiveColor"
                :inactiveIconClass="item.inactiveIconClass"
                :inactiveText="item.inactiveText"
                :inactiveValue="item.inactiveValue"
                :model.sync="form[item.model]"
                :name="item.name"
                :validateEvent="item.validateEvent"
                :width="item.width"
                v-else-if="item.type==='switch'"
              ></my-switch>
              <!--timeselect时间选择框-->
              <my-timeselect
                :change="item.change"
                :clearable="item.clearable"
                :editable="item.editable"
                :model.sync="form[item.model]"
                :pickerOptions="item.pickerOptions"
                :valueFormat="item.valueFormat"
                v-else-if="item.type==='timeSelect'"
              ></my-timeselect>
              <!--transfer穿梭框-->
              <my-transfer
                :buttonTexts="item.buttonTexts"
                :change="item.change"
                :data="item.data"
                :model.sync="form[item.model]"
                :props="item.props"
                :titles="item.titles"
                v-else-if="item.type==='transfer'"
              ></my-transfer>
              <!--upload上传插件-->
              <my-upload
                :action="item.action"
                :autoUpload="item.autoUpload"
                :data="item.data"
                :disabled="item.disabled"
                :drag="item.drag"
                :handleBeforeRemove="item.handleBeforeRemove"
                :handleBeforeUpload="item.handleBeforeUpload"
                :handleChange="item.handleChange"
                :handleError="item.handleError"
                :handleExceed="item.handleExceed"
                :handlePreview="item.handlePreview"
                :handleProgress="item.handleProgress"
                :handleRemove="item.handleRemove"
                :handleSuccess="item.handleSuccess"
                :headers="item.headers"
                :httpRequest="item.httpRequest"
                :limit="item.limit"
                :listType="item.listType"
                :model.sync="form[item.model]"
                :multiple="item.multiple"
                :name="item.name"
                :showFileList="item.showFileList"
                :status="item.status"
                ref="myUpload"
                v-else-if="item.type==='upload'"
              ></my-upload>
              <!--按钮组选项卡，暂只能单选-->

              <!--自定义插槽-->
              <slot :model="item.model" :name="item.model" v-else-if="item.type === 'slot'"></slot>
            </el-form-item>
          </el-col>
        </el-row>
      </virtual-list>
    </el-form>
  </div>
</template>

<script>
import virtualList from 'vue-virtual-scroll-list'

import myText from './myText'
import myButton from './myButton'
import myInput from './myInput'
import myRadio from './myRadio'
import myCheckbox from './myCheckbox'
import MySelect from './mySelect'
import myDatepicker from './myDatepicker'
import myTimeselect from './myTimeselect'
import myTransfer from './myTransfer'
import myInputNumber from './myInputNumber'
import myAutocomplete from './myAutocomplete'
import myUpload from './myUpload'
import mySwitch from './mySwitch'

export default {
  name: 'myForm',
  components: {
    virtualList,
    myText,
    myButton,
    myInput,
    myRadio,
    myCheckbox,
    MySelect,
    myDatepicker,
    myTimeselect,
    myTransfer,
    myInputNumber,
    myAutocomplete,
    myUpload,
    mySwitch
  },
  props: {
    // 传入数组对象[{model:'',label:'',type:'',options:[],(disabled:'')}]，用于表单渲染生成
    data: {
      type: Array,
      required: true
    },
    // 传入form绑定对象
    form: {
      type: Object,
      required: true
    },
    // 传入表单验证规则
    rules: {
      type: Object,
      default () {
        return {}
      }
    },
    // 是否启用虚拟滚动list
    isVirtaulList: {
      type: Boolean,
      default () {
        return false
      }
    },
    // 虚拟滚动每行item高度
    virtualListSize: {
      type: Number,
      default () {
        return 50
      }
    },
    // 虚拟滚动可见行数
    virtualListRemain: {
      type: Number,
      default () {
        return 10
      }
    },
    // 虚拟滚动当前所在item，用于滚动到对应item
    virtualListStart: {
      type: Number,
      default () {
        return 0
      }
    },
    // 栅格栏的分配
    span: {
      type: Number,
      default () {
        return 24
      }
    },
    // 用于控制该表单内组件的尺寸medium / small / mini
    size: {
      type: String,
      default () {
        return 'medium'
      }
    },
    // 栅格栏之间的间隔
    gutter: {
      type: Number,
      default () {
        return 0
      }
    },
    // label宽度
    formLabelWidth: {
      type: String,
      default () {
        return '120px'
      }
    },
    // 是否显示校验错误信息
    showMessage: {
      type: Boolean,
      default () {
        return true
      }
    },
    // 当前表单外部样式
    formClass: {
      type: [String, Object],
      default () {
        return ''
      }
    }
  },
  data () {
    return {
      curVirtualListRemain: this.virtualListRemain // 当前虚拟滚动组件实际remain绑定值，因为要做非滚动情况，需要把remain值改变
    }
  },
  computed: {
    // 对数据源做二维数组转换，[[{}],[{}]] 一个元素代表一个列表 主要为了isVirtaulList的使用
    curData: function () {
      const data = this.data
      const ary = []
      let temp = 0
      let tempAry = []

      for (let i = 0; i < data.length; i++) {
        if (Array.isArray(data[i])) {
          ary.push(data[i])
        } else {
          // 要是为对象，要判断是否成一行 栅格占用24
          // row span、pull、push、offset加起来为24，要是span未设置默认24
          // 下一项若是数组 直接把当前几项合并成一行来算

          tempAry.push(data[i])

          // 当前数组项
          const span = data[i].span || 24
          const pull = data[i].pull || 0
          const push = data[i].push || 0
          const offset = data[i].offset || 0
          const allSpan = span + pull + push + offset

          // 下一个数组项
          let nextSpan = 0
          let nextPull = 0
          let nextPush = 0
          let nextOffset = 0
          let nextAllSpan = 0
          if (i + 1 < data.length) {
            nextSpan = data[i + 1].span || 24
            nextPull = data[i + 1].pull || 0
            nextPush = data[i + 1].push || 0
            nextOffset = data[i + 1].offset || 0
            nextAllSpan = nextSpan + nextPull + nextPush + nextOffset
          }

          if (allSpan < 24 && (i + 1 < data.length && nextAllSpan < 24)) {
            temp = temp + allSpan
          } else {
            ary.push(tempAry)
            temp = 0
            tempAry = []
          }
        }
      }

      return ary
    }
  },
  watch: {
    data: {
      handler (val, oldVal) {
        if (!this.isVirtaulList) {
          this.curVirtualListRemain = val.length
        }
      },
      deep: true,
      immediate: true
    },
    virtualListStart: {
      handler (val, oldVal) {
        // console.log(val);
      },
      deep: true,
      immediate: true
    }
  },
  created () {},
  methods: {
    getVariableHeight (itemIndex) {
      return (this.curData[itemIndex] && this.curData[itemIndex][0].vHeight) || this.virtualListSize
    }
  }
}
</script>

<style lang="scss">
.myForm {
  .el-form {
    pre {
      font-family: inherit;
      white-space: normal;
    }

    .el-row {
      padding-right: 15px;
    }
  }

  .non-virtual-list {
    overflow-y: initial !important;
    height: auto !important;

    .el-row {
      padding: initial !important;
    }
  }
}
</style>
